/*
 * Copyright 2009 Colin Prinn
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package net.recursv.motific.at;

import net.recursv.motific.at.runner.AtRunner;
import net.recursv.motific.at.runner.AtScript;
import net.recursv.motific.at.runner.ScriptBuilder;
import net.recursv.motific.at.scene.ConstructManager;
import net.recursv.motific.at.utils.KeyMap;
import net.recursv.motific.utils.WrappedException;
import net.recursv.motific.utils.files.FileSystem;

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Created by: recursv
 * Date: 9/08/2009
 * Time: 12:07:17 AM
 *
 * @noinspection MissedExecutable
 */
public abstract class AtMidlet extends MIDlet {
    private AtRunner _runner;
    private static AtMidlet _instance;
    private AtDisplay _display;

    protected AtMidlet() {
        _instance = this;
    }

    protected void startApp() throws MIDletStateChangeException {
        displaySplashScreen();

        initKeyMap();

        initConstructs();

        createRunner();

        displayTestScreen();

        startRunner();
    }

    private void initConstructs() {
        ConstructManager.initialise(getRulesDirectory());
    }

    private void displaySplashScreen() {
        Display.getDisplay(this).setCurrent(new LoadingTestsCanvas());
    }

    private void initKeyMap() {
        try {
            Hashtable map = FileSystem.readPropertiesResource("/keymap.properties");

            // This little loop converts the hashtable values from strings to integers as is expected by the keymap
            Enumeration enumeration = map.keys();
            while (enumeration.hasMoreElements()) {
                String name = (String) enumeration.nextElement();
                String s = (String) map.get(name);
                int i = Integer.parseInt(s);
                Integer integer = new Integer(i);
                map.put(name, integer);
            }

            KeyMap.initialise(map);
        } catch (IOException e) {
            throw new WrappedException(e);
        }
    }

    private void displayTestScreen() {
        _display = new AtDisplay(this);
        Display.getDisplay(this).setCurrent(_display);
    }

    private void createRunner() {
        ScriptBuilder builder = new ScriptBuilder();
        _runner = new AtRunner(builder.createIterator(getScriptDirectory()), getTestMidletClass());
        AtScript.TIMEOUT = getTimeoutThreshold();
    }

    private void startRunner() {
        _runner.addListener(new ResultHandler());
        _runner.addListener(_display);
        _runner.execute();
    }

    protected void pauseApp() {
        throw new RuntimeException("not implemented");
    }

    protected void destroyApp(boolean b) throws MIDletStateChangeException {
        if (_runner != null) {
            _runner.cease();
            _runner = null;
        }
    }

    protected abstract Class getTestMidletClass();

    protected abstract long getTimeoutThreshold();

    public abstract String getScriptDirectory();

    protected abstract String getRulesDirectory();

    public static void repaint() {
        _instance._display.repaint();
    }
}
